package com.phoenix.jsef.common;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;

/**
 * @version V1.0
 * @ClassName: CacheManagerImpl
 * @Description:TODO(用于缓存本地数据的简单管理实现功能)
 * @author: 李启联
 * @date: 2018-11-22 10:07
 * @Copyright: Copyright (c), 2018-2018
 * 申明：本内容未经作者本人同意,禁止外泄以及用于其他的商业项目.
 */
public class CacheManagerImpl implements ICacheManager {

    /**
     * 缓存对象
     */
    private static final Map<String, CacheEntity> caches = new ConcurrentHashMap<String, CacheEntity>();

    /**
     * 定时器线程池，用于清除过期缓存
     */
    private final static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();


    @Override
    public void putCache(String key, CacheEntity cache) {
        caches.put(key, cache);
    }

    @Override
    public void putCache(String key, Object datas, long timeOut) {
        timeOut = timeOut > 0 ? timeOut : 0L;
        if(timeOut >0){
            Future future = executor.schedule(new Runnable() {
                @Override
                public void run() {
                    //过期后清除该键值对
                    synchronized (CacheManagerImpl.class) {
                        clearByKey(key);
                    }
                }
            },timeOut,TimeUnit.MINUTES);
            putCache(key, new CacheEntity(datas, timeOut, System.currentTimeMillis(), future));
        }else {
            putCache(key, new CacheEntity(datas, timeOut, System.currentTimeMillis(), null));
        }
    }

    @Override
    public void putCache(String key, Object datas, long timeOut, TimeUnit timeUnit) {
        timeOut = timeOut > 0 ? timeOut : 0L;
        if(timeOut >0){
            Future future = executor.schedule(new Runnable() {
                @Override
                public void run() {
                    //过期后清除该键值对
                    synchronized (CacheManagerImpl.class) {
                        clearByKey(key);
                    }
                }
            },timeOut,timeUnit);
            putCache(key, new CacheEntity(datas, timeOut,timeUnit,System.currentTimeMillis(), future));
        }else {
            putCache(key, new CacheEntity(datas, timeOut, timeUnit,System.currentTimeMillis(),null));
        }
    }

    @Override
    public CacheEntity getCacheByKey(String key) {
        if (this.isContains(key)) {
            return caches.get(key);
        }
        return null;
    }

    @Override
    public Object getCacheDataByKey(String key) {
        if (this.isContains(key)) {
            return caches.get(key).getDatas();
        }
        return null;
    }

    @Override
    public Map<String, CacheEntity> getCacheAll() {
        return caches;
    }

    @Override
    public boolean isContains(String key) {
        return caches.containsKey(key);
    }

    @Override
    public void clearAll() {
        //清除所有缓存对应定时器
        for (CacheEntity entity: caches.values()) {
            Future future = entity.getFuture();
            //清除对应定时器
            if(null != future)
                future.cancel(true);
        }
        caches.clear();
    }

    @Override
    public void clearByKey(String key) {
        if (this.isContains(key)) {
            Future future = caches.get(key).getFuture();
            //清除对应定时器
            if(null != future)
                future.cancel(true);
            caches.remove(key);
        }
    }

    @Override
    public boolean isTimeOut(String key) {
        if (!caches.containsKey(key)) {
            return true;
        }
        CacheEntity cache = caches.get(key);
        TimeUnit timeUnit = cache.getTimeUnit();
        long timeOut = cache.getTimeOut();
        long lastRefreshTime = cache.getLastRefeshTime();
        if (timeOut == 0 || System.currentTimeMillis() - lastRefreshTime >= timeUnit.toMillis(timeOut)) {
            return true;
        }
        return false;
    }

    @Override
    public Set<String> getAllKeys() {
        return caches.keySet();
    }
}